package edu.washington.cs.workflow.analysis;

import com.ibm.wala.analysis.typeInference.TypeAbstraction;
import com.ibm.wala.analysis.typeInference.TypeInference;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.TypeReference;

import edu.washington.cs.workflow.util.WALAUtils;

public class GUILabelIdentifier {
	
	public boolean isLabelSettingMethod(SSAInvokeInstruction invoke) {
		return invoke.toString().indexOf("<init>") != -1;
	}
	
	/**
	 * e.g., in button.addActionListener(), button's index is 0
	 * */
	public int getGUIIndexInActionAdding(SSAInvokeInstruction invoke) {
		return invoke.getUse(0);
	}
	
	/**
	 * e.g., button.<init>(value)  or  button.setText(value), button's index is 0
	 * */
	public int getGUIIndexInLabelSetting(SSAInvokeInstruction invoke) {
		return invoke.getUse(0);
	} 
	
	/**
	 * e.g., button.setText(value); value's index is 1
	 * */
	public int getLabelVarIndex(SSAInvokeInstruction invoke) {
		return invoke.getUse(1);
	}
	
	
	/**
	 * e.g., button.getText() is a value-getting call
	 * */
	public boolean isGUIValueGettingCall(SSAInvokeInstruction invoke) {
		String methodName = invoke.getCallSite().getDeclaredTarget().getName().toString();
		return methodName.equals("getSelectedItem") || 
		    methodName.equals("getText");
	}
	
	public String getLabelForGUIObject(CGNode node, SSAInvokeInstruction labelSetInstr, int labelVarIndex) {
		SymbolTable sTable = node.getIR().getSymbolTable();
		if(sTable.isStringConstant(labelVarIndex)) {
		    return WALAUtils.getVarValue(node, labelVarIndex);
		} else {
			System.err.println(WALAUtils.getAllIRAsString(node));
			TypeInference ti = TypeInference.make(node.getIR(), false);
			TypeAbstraction type = ti.getType(labelVarIndex);
			TypeReference tr = type.getTypeReference();
			if(tr.isArrayType() && tr.getArrayElementType().getName().toString().equals("Ljava/lang/String")) {
				return getStringArrayContent(node, labelVarIndex); //"string array type";
			} else {
				return "";
			}
		}
	}
	
	private String getStringArrayContent(CGNode node, int arrayValueNum) {
		StringBuilder sb = new StringBuilder();
		
		for(SSAInstruction ssa : WALAUtils.getAllIRs(node)) {
			if(ssa instanceof SSAArrayStoreInstruction) {
				SSAArrayStoreInstruction storeInstr = (SSAArrayStoreInstruction)ssa;
				if(storeInstr.getArrayRef() == arrayValueNum) {
					int vn = storeInstr.getValue();
					sb.append(node.getIR().getSymbolTable().getStringValue(vn));
					sb.append(", ");
				}
			}
		}
		
		if(sb.length() == 0) {
			return "No_Str_Array_Content";
		}
		return sb.toString();
	}
}